# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
# (C) 2012 Remek Zajac
#!/usr/bin/python
import cairo
import pyGeometry
import math

g_colourDescriptors = {'Red': (1.0,0.0,0.0,0.5), "Max": (0.0,0.3,1.0,1.0), "Min": (1.0,0.0,0.0,0.5)}
g_widthDescriptors = {'Thin': 1, 'Normal': 4, 'Thick': 7}

class TripPathToolWithSpeed:
    DefaultStyleDescriptorMAX = {'Colour':g_colourDescriptors['Max'], 'Width':g_widthDescriptors['Thick']}
    DefaultStyleDescriptorMIN = {'Colour':g_colourDescriptors['Min'], 'Width':g_widthDescriptors['Thick']}
    StyleDescriptors = {'Default':{'Max':DefaultStyleDescriptorMAX, 'Min':DefaultStyleDescriptorMIN}}
    def __init__(self):
        self.lastPoint = None
        self.lastStationaryPoint = None

    def init(self, cr, style = 'Default'):
        self.styleDescriptor = TripPathToolWithSpeed.StyleDescriptors[style]
        self.cr = cr
        self.speedStyleModifier = None

    def draw(self, point, speedStyleModifierPrecent = 50):
        speedStyleModifer = speedStyleModifierPrecent/100.0
        if not self.lastPoint or (not self.lastPoint[2] and not point[2]):
            self.lastPoint = point
            return True
        #calculate width
        maxWidth = self.styleDescriptor['Max']['Width']
        minWidth = self.styleDescriptor['Min']['Width']
        width = maxWidth*speedStyleModifer+minWidth*(1-speedStyleModifer)
        vector = pyGeometry.Vector((self.lastPoint, point))
        if vector.length() <= width:
            #segment too short, refuse to draw
            return False
        self.cr.set_line_width(width)

        #calculate colour for the segment
        maxColour = self.styleDescriptor['Max']['Colour']
        minColour = self.styleDescriptor['Min']['Colour']
        red   = maxColour[0]*speedStyleModifer+minColour[0]*(1-speedStyleModifer)
        green = maxColour[1]*speedStyleModifer+minColour[1]*(1-speedStyleModifer)
        blue  = maxColour[2]*speedStyleModifer+minColour[2]*(1-speedStyleModifer)
        alpha = maxColour[3]*speedStyleModifer+minColour[3]*(1-speedStyleModifer)        
        self.cr.set_source_rgba(red, green, blue, alpha)

        self.cr.move_to(self.lastPoint[0], self.lastPoint[1])
        self.cr.line_to(point[0], point[1])
        self.cr.stroke()
        self.lastPoint = point
        return True

    def markStationary(self, point):      
        if not point[2]:
            #invisible, don't bother drawing
            return
        maxWidth = self.styleDescriptor['Max']['Width']
        if (self.lastStationaryPoint and pyGeometry.Vector((self.lastStationaryPoint, point)).length() <= maxWidth):
            #segment too short, refuse to draw
            return
        self.cr.arc(point[0], point[1], maxWidth, 0, 2*math.pi)
        self.cr.set_source_rgb(1,0,0)
        self.cr.set_line_width(maxWidth/2)
        self.cr.stroke_preserve()
        self.cr.set_source_rgb(1,1,1)
        self.cr.fill()
        self.lastStationaryPoint = point

class RoadTool:
    def __init__(self):
        self.lastPoint = None

    def init(self, cr, way, region):
        self.cr = cr
        self.way = way
        self.region = region

    def draw(self, point):
        if not self.lastPoint or not self.region.intersects((self.lastPoint, point)):
            self.lastPoint = point
            return True

        colour = self.way.colour.colour()
        self.cr.set_source_rgba(colour[0],colour[1], colour[2], colour[3])
        self.cr.set_line_width(self.way.width())
        self.cr.move_to(self.lastPoint[0], self.lastPoint[1])
        self.cr.line_to(point[0], point[1])
        self.cr.stroke()
        self.lastPoint = point
        return True

class NodeTool:
    def __init__(self):
        pass

    def init(self, cr):
        self.cr = cr
        
    def draw(self, point):
        diagonal1 = pyGeometry.Vector((2,2))
        diagonal2 = pyGeometry.Vector((-2,2))
        se = diagonal1.addToPoint(point)
        diagonal1 = diagonal1.reverse()
        nw = diagonal1.addToPoint(point)
        ne = diagonal2.addToPoint(point)
        diagonal2 = diagonal2.reverse()
        sw = diagonal2.addToPoint(point)
        self.cr.set_source_rgba(0, 0, 0.5, 0.5)
        self.cr.set_line_width(1)
        self.cr.move_to(nw[0], nw[1])
        self.cr.line_to(se[0], se[1])
        self.cr.move_to(ne[0], ne[1])
        self.cr.line_to(sw[0], sw[1])
        self.cr.stroke()
        
class GeoDrawingToolkit:
    def __init__(self):
        pass

    def pathTool(self, style = None):
        return TripPathToolWithSpeed()

    def nodeTool(self, style = None):
        return NodeTool()

    def roadTool(self, style = None):
        return RoadTool()
        
